﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Drawing;

namespace MacomberMapSystem.Common.Exports
{
    /// <summary>
    /// This class holds information on a DDL exporter target
    /// </summary>
    public class MM_DDL_Exporter_Target : IDisposable
    {
        #region Variable Declarations
        /// <summary>The current indentation</summary>
        public int Indentation = 0;

        /// <summary>Our target</summary>
        public TextWriter Target;
        #endregion

        #region Initialization
        /// <summary>
        /// Initialize a new exporter target
        /// </summary>
        /// <param name="Target"></param>
        public MM_DDL_Exporter_Target(TextWriter Target)
        {
            this.Target = Target;
        }
        #endregion

        #region Public interfaces
        /// <summary>
        /// Write an attribute out to the DDL export
        /// </summary>
        /// <param name="Name"></param>
        /// <param name="Value"></param>
        public void WriteAttribute(String Name, String Value)
        {
            if (Name == "Value")
            {
                WriteLine(new String('\t', Indentation) + "localize \"" + Value + "\"");
                return;
            }
            if (Value == "false")
                Write(new String('\t', Indentation) + "not " + Name);
            else
                Write(new String('\t', Indentation) + Name);

            if (String.IsNullOrEmpty(Value))
                Write(" ");
            else if (Name == "localize")
                Write(" \"" + Value + "\"");
            else if (Name == "cam" || Name == "gab" || Name == "keyset")
                Write(" \"" + Value + "\" ");
            else if (Name == "size" || Name == "position" || Name == "factor" || Name == "lo_declutter" || Name == "hi_declutter" || Name == "format" || Name == "width" || Name == "height" || Name == "justification")
                Write("(" + Value + ")");
            else if (Value == "left arrow" || Value == "up arrow" || Value == "right arrow" || Value == "down arrow")
                Write("(bitmap(\"" + Value + "\"))");
            else if (Name == "origin")
                Write("(" + Value.Replace(',', ' ') + ")");
            else if (Name == "point")
            {
                string[] splStr = Value.Split(',');
                WriteLine("(" + splStr[0] + " " + splStr[1] + ")");
                for (int a = 2; a < splStr.Length; a += 2)
                    WriteAttribute(Name, float.Parse(splStr[a]), float.Parse(splStr[a + 1]));
            }
            else if (Value != "true" && Value != "false")
                Write("(\"" + Value + "\") ");
            if (Indentation == 0)
                WriteLine(";");
            else
                WriteLine();
        }

        /// <summary>
        /// Write a text box
        /// </summary>
        /// <param name="Text"></param>
        /// <param name="Location"></param>
        /// <param name="Foreground"></param>
        /// <param name="Background"></param>
        /// <param name="Font"></param>
        /// <param name="FontSize"></param>
        /// <param name="Underline"></param>
        /// <param name="Bold"></param>
        /// <param name="Italics"></param>
        /// <param name="xLocked"></param>
        /// <param name="yLocked"></param>
        public void WriteText(String Text, Point Location, String Foreground, String Background, String Font, int FontSize, bool Underline, bool Bold, bool Italics, bool xLocked, bool yLocked)
        {
            WriteStartTag("text", "");
            WriteStartTag("gab", "");
            if (!String.IsNullOrEmpty(Foreground))
                WriteAttribute("foreground", Foreground);
            if (!String.IsNullOrEmpty(Background))
                WriteAttribute("background", Background);
            if (!String.IsNullOrEmpty(Font))
                WriteAttribute("font_family", Font);
            if (FontSize > 0)
                WriteAttribute("font_size", FontSize);
            if (Underline)
                WriteAttribute("font_underline");
            if (Italics && Bold)
                WriteAttribute("font_style", "Bold Italic");
            else if (Italics)
                WriteAttribute("font_style", "Italic");
            else if (Bold)
                WriteAttribute("font_style", "Bold");
            WriteEndTag();
            WriteAttribute("origin", Location.X, Location.Y);
            if (xLocked)
                WriteAttribute("xlocked");
            if (yLocked)
                WriteAttribute("ylocked");
            WriteAttribute("localize", Text);
            WriteEndTag();
        }

        /// <summary>
        /// Write a text box
        /// </summary>
        /// <param name="Text"></param>
        /// <param name="Cam"></param>
        /// <param name="Location"></param>
        /// <param name="Foreground"></param>
        /// <param name="Background"></param>
        /// <param name="Font"></param>
        /// <param name="FontSize"></param>
        /// <param name="Underline"></param>
        /// <param name="Bold"></param>
        /// <param name="Italics"></param>
        /// <param name="xLocked"></param>
        /// <param name="yLocked"></param>
        public void WriteTextWithCam(String Text, String Cam, Point Location, String Foreground, String Background, String Font, int FontSize, bool Underline, bool Bold, bool Italics, bool xLocked, bool yLocked)
        {
            WriteStartTag("text", "");
            WriteStartTag("gab", "");
            if (!String.IsNullOrEmpty(Foreground))
                WriteAttribute("foreground", "White");
            if (!String.IsNullOrEmpty(Background))
                WriteAttribute("background", Background);
            if (!String.IsNullOrEmpty(Font))
                WriteAttribute("font_family", Font);
            if (FontSize > 0)
                WriteAttribute("font_size", FontSize);
            if (Underline)
                WriteAttribute("font_underline");
            if (Italics && Bold)
                WriteAttribute("font_style", "Bold Italic");
            else if (Italics)
                WriteAttribute("font_style", "Italic");
            else if (Bold)
                WriteAttribute("font_style", "Bold");
            WriteEndTag();
            WriteAttribute("cam", Cam);
            WriteAttribute("set", "ERCOTONELINES");
            WriteAttribute("origin", Location.X, Location.Y);
            if (xLocked)
                WriteAttribute("xlocked");
            if (yLocked)
                WriteAttribute("ylocked");
            WriteAttribute("localize", Text);
            WriteEndTag();

        }

        /// <summary>
        /// Write text using an existing gab
        /// </summary>
        /// <param name="Text"></param>
        /// <param name="Gab"></param>
        /// <param name="Location"></param>
        /// <param name="xlocked"></param>
        /// <param name="ylocked"></param>
        public void WriteTextWithGab(String Text, String Gab, Point Location, bool xlocked, bool ylocked)
        {
            WriteStartTag("text", "");
            WriteAttribute("gab", Gab);
            WriteAttribute("set", "ERCOTONELINES");
            WriteAttribute("origin", Location.X, Location.Y);
            if (xlocked)
                WriteAttribute("xlocked");
            if (ylocked)
                WriteAttribute("ylocked");
            WriteAttribute("localize", Text);
            WriteEndTag();
        }

        /// <summary>
        /// Write text using an existing gab
        /// </summary>
        /// <param name="Text"></param>
        /// <param name="Gab"></param>
        /// <param name="Location"></param>
        /// <param name="xlocked"></param>
        /// <param name="ylocked"></param>
        public void WriteTextWithGabAndToolTip(String Text, String Gab, Point Location, String ToolTip, bool xlocked, bool ylocked)
        {
            WriteStartTag("text", "");
            WriteAttribute("gab", Gab);
            WriteAttribute("set", "ERCOTONELINES");
            WriteAttribute("origin", Location.X, Location.Y);
            if (xlocked)
                WriteAttribute("xlocked");
            if (ylocked)
                WriteAttribute("ylocked");
            WriteAttribute("tool_tip(localize \"" + ToolTip.Replace("\r\n", "\r\r\n") + "\")");
            WriteAttribute("localize", Text);
            WriteEndTag();

        }


        /// <summary>
        /// Write text using an existing gab
        /// </summary>
        /// <param name="Text"></param>
        /// <param name="Gab"></param>
        /// <param name="Location"></param>
        /// <param name="xlocked"></param>
        /// <param name="ylocked"></param>
        public void WriteTextWithGabAndToolTipAndKeySet(String Text, String Gab, Point Location, String ToolTip, bool xlocked, bool ylocked, String KeySet)
        {
            WriteStartTag("text", "");
            WriteAttribute("gab", Gab);
            WriteAttribute("set", "ERCOTONELINES");
            WriteAttribute("keyset", KeySet);
            WriteAttribute("set", "ERCOTONELINES");
            WriteAttribute("origin", Location.X, Location.Y);
            if (xlocked)
                WriteAttribute("xlocked");
            if (ylocked)
                WriteAttribute("ylocked");
            WriteAttribute("tool_tip(localize \"" + ToolTip.Replace("\r\n", "\r\r\n") + "\")");
            WriteAttribute("localize", Text);
            WriteEndTag();
        }

        /// <summary>
        /// Write text using an existing gab
        /// </summary>
        /// <param name="Text"></param>
        /// <param name="Gab"></param>
        /// <param name="Location"></param>
        /// <param name="xlocked"></param>
        /// <param name="ylocked"></param>
        /// <param name="Cam"></param>
        public void WriteTextWithCamAndGab(String Text, String Cam, String Gab, Point Location, bool xlocked, bool ylocked)
        {
            WriteStartTag("text", "");
            WriteAttribute("gab", Gab);
            WriteAttribute("set", "ERCOTONELINES");
            WriteAttribute("cam", Cam);
            WriteAttribute("set", "ERCOTONELINES");
            WriteAttribute("origin", Location.X, Location.Y);
            if (xlocked)
                WriteAttribute("xlocked");
            if (ylocked)
                WriteAttribute("ylocked");
            WriteAttribute("localize", Text);
            WriteEndTag();
        }

        /// <summary>
        /// Write out the DDL header
        /// </summary>
        /// <param name="VersionInfo"></param>
        public void WriteHeader(String VersionInfo)
        {
            this.WriteLine();
            this.WriteAttribute("version", VersionInfo);
            this.Indentation++;
            this.WriteLine();
        }

        /// <summary>
        /// Write an attribute out to the DDL export
        /// </summary>
        /// <param name="Name">The name of the attribute</param>        
        public void WriteAttribute(String Name)
        {
            Write(new String('\t', Indentation) + Name + " ");
            if (Indentation == 0)
                WriteLine(";");
            else
                WriteLine();
        }

        /// <summary>
        /// Write an attribute out to the DDL export
        /// </summary>
        /// <param name="Name">The name of the attribute</param>
        /// <param name="Value">The value of the attribute</param>
        public void WriteAttribute(String Name, float Value)
        {
            Write(new String('\t', Indentation) + Name + "(" + Value + ") ");
            if (Indentation == 0)
                WriteLine(";");
            else
                WriteLine();
        }

        /// <summary>
        /// Write an attribute out to the DDL export
        /// </summary>
        /// <param name="Name">The name of the attribute</param>
        /// <param name="Value1">The value of the attribute</param>
        /// <param name="Value2">The second value of the attribute</param>
        public void WriteAttribute(String Name, float Value1, float Value2)
        {
            Write(new String('\t', Indentation) + Name + "(" + Value1 + " " + Value2 + ") ");
            if (Indentation == 0)
                WriteLine(";");
            else
                WriteLine();
        }

        /// <summary>
        /// Write an attribute out to the DDL export
        /// </summary>
        /// <param name="Name1">The name of the attribute</param>
        /// <param name="Name2">The second name of the attribute</param>
        /// <param name="Value">The value of the attribute</param>
        public void WriteAttribute(String Name1, String Name2, String Value)
        {
            WriteLine(new String('\t', Indentation) + Name1 + "(" + Name2 + " \"" + Value + "\")");
        }

        /// <summary>
        /// Write the starting tag of component
        /// </summary>
        /// <param name="Name"></param>
        /// <param name="Value"></param>
        public void WriteStartTag(string Name, string Value)
        {
            if (String.IsNullOrEmpty(Value))
                WriteLine(String.Format("{0}{1} ", new String('\t', Indentation), Name));
            else
                WriteLine(String.Format("{0}{1} \"{2}\"", new String('\t', Indentation), Name, Value));
            WriteLine(new String('\t', Indentation) + "(");
            Indentation++;
        }

        /// <summary>
        /// Write the end of a tag
        /// </summary>
        public void WriteEndTag()
        {
            Indentation--;
            if (Indentation == 1)
                WriteLine(new String('\t', Indentation) + ");");
            else
                WriteLine(new String('\t', Indentation) + ")");
        }

        /// <summary>
        /// Write a rotated attribute
        /// </summary>
        /// <param name="Name"></param>
        /// <param name="X"></param>
        /// <param name="Y"></param>
        /// <param name="Height"></param>
        /// <param name="Width"></param>
        /// <param name="Angle"></param>
        public void WriteRotatedAttribute(string Name, int X, int Y, int Width, int Height, int Angle)
        {
            if (Angle == 0)
                WriteAttribute(Name, X, Y);
            else if (Angle == 90)
                WriteAttribute(Name, Height - Y, Width - X);
            else if (Angle == 180)
                WriteAttribute(Name, Width - X, Height - Y);
            else if (Angle == 270)
                WriteAttribute(Name, Y, X);

        }

        /// <summary>
        /// Write out a composite key
        /// </summary>
        /// <param name="Keys"></param>
        public void WriteKey(params string[] Keys)
        {
            if (Keys.Length == 1 && Keys[0] == "")
                return;
            WriteStartTag("composite_key", "");
            foreach (string str in Keys)
            {
                string[] splStr = str.ToUpper().Split('=');
                WriteAttribute("record", splStr[0]);
                WriteAttribute("record_key", splStr[1]);
            }
            WriteEndTag();
        }

        /// <summary>
        /// Write out an old-style picture with associated records
        /// </summary>
        /// <param name="LabelName"></param>
        /// <param name="Location"></param>
        /// <param name="Keys"></param>
        public void WriteDataBoundPicture(string LabelName, Point Location, params string[] Keys)
        {
            WriteStartTag("picture", LabelName);
            WriteAttribute("set", "ERCOTONELINES");
            WriteAttribute("origin", Location.X, Location.Y);
            WriteKey(Keys);
            WriteEndTag();
        }

        /// <summary>
        /// Write out an old-style picture with associated records 
        /// </summary>
        /// <param name="LabelName"></param>
        /// <param name="ToolTip"></param>
        /// <param name="Location"></param>
        /// <param name="Keys"></param>
        public void WriteDataBoundPictureWithToolTip(string LabelName, string ToolTip, Point Location, params string[] Keys)
        {
            WriteDataBoundPictureWithToolTip(LabelName, ToolTip, Location, false, false, Keys);  
        }

        /// <summary>
        /// Write out an old-style picture with associated records
        /// </summary>
        /// <param name="LabelName"></param>
        /// <param name="ToolTip"></param>
        /// <param name="Location"></param>
        /// <param name="Keys"></param>
        public void WriteDataBoundPictureWithToolTip(string LabelName, string ToolTip, Point Location, bool XLocked, bool YLocked, params string[] Keys)
        {
            WriteStartTag("picture", LabelName);
            WriteAttribute("set", "ERCOTONELINES");
            WriteAttribute("origin", Location.X, Location.Y);
            if (XLocked)
                WriteAttribute("xlocked");
            if (YLocked)
                WriteAttribute("ylocked");


            WriteAttribute("tool_tip(localize \"" + ToolTip.Replace("\r\n", "\r\r\n") + "\")");
            WriteKey(Keys);
            WriteEndTag();
        }


        /// <summary>
        /// Write out an old-style picture with associated records
        /// </summary>
        /// <param name="SymbolName"></param>
        /// <param name="Location"></param>        
        public void WriteSymbol(string SymbolName, Point Location)
        {
            String[] splStr = SymbolName.Split('\\');
            WriteStartTag("symbol", splStr[splStr.Length - 1]);
            if (splStr.Length == 1)
                WriteAttribute("set", "ERCOTONELINES");
            else
                WriteAttribute("set", splStr[0]);
            WriteAttribute("origin", Location.X, Location.Y);
            WriteEndTag();
        }

        /// <summary>
        /// Write out an old-style picture with associated records
        /// </summary>
        /// <param name="SymbolName"></param>
        /// <param name="Location"></param>        
        /// <param name="Offset"></param>
        /// <param name="ToolTip"></param>
        public void WriteSymbolWithToolTip(string SymbolName, Point Location, Point Offset, String ToolTip)
        {
            WriteStartTag("symbol", SymbolName);
            WriteAttribute("set", "ERCOTONELINES");
            WriteAttribute("origin", Location.X + Offset.X, Location.Y + Offset.Y);
            WriteAttribute("tool_tip(localize \"" + ToolTip.Replace("\r\n", "\r\r\n") + "\")");
            WriteEndTag();
        }

        /// <summary>
        /// Write out an old-style picture with associated records
        /// </summary>
        /// <param name="SymbolName"></param>
        /// <param name="Location"></param>                
        /// <param name="ToolTip"></param>
        public void WriteSymbolWithToolTip(string SymbolName, Point Location, String ToolTip)
        {
            WriteStartTag("symbol", SymbolName);
            WriteAttribute("set", "ERCOTONELINES");
            WriteAttribute("origin", Location.X, Location.Y);
            WriteAttribute("tool_tip(localize \"" + ToolTip.Replace("\r\n", "\r\r\n") + "\")");
            WriteEndTag();
        }

        /// <summary>
        /// Write out an old-style picture with associated records
        /// </summary>
        /// <param name="SymbolName"></param>
        /// <param name="Location"></param>        
        /// <param name="Keyset"></param>
        public void WriteSymbolWithKeyset(string SymbolName, Point Location, String Keyset)
        {
            WriteStartTag("symbol", SymbolName);
            WriteAttribute("set", "ERCOTONELINES");
            if (!String.IsNullOrEmpty(Keyset))
            {
                WriteAttribute("keyset", Keyset);
                WriteAttribute("set", "ERCOTONELINES");
            }
            WriteAttribute("origin", Location.X, Location.Y);
            WriteEndTag();
        }


        /// <summary>
        /// Write out an old-style picture with associated records
        /// </summary>
        /// <param name="SymbolName"></param>
        /// <param name="Location"></param>  
        /// <param name="Offset"></param>
        public void WriteSymbol(string SymbolName, Point Location, Point Offset)
        {
            WriteStartTag("symbol", SymbolName);
            WriteAttribute("set", "ERCOTONELINES");
            WriteAttribute("origin", Location.X + Offset.X, Location.Y + Offset.Y);
            WriteEndTag();
        }

        /// <summary>
        /// Write out an old-style picture with associated records
        /// </summary>
        /// <param name="SymbolName"></param>
        /// <param name="Location"></param>  
        /// <param name="Cam"></param>
        /// <param name="Offset"></param>
        public void WriteSymbolWithCam(string SymbolName, Point Location, Point Offset, String Cam)
        {
            WriteStartTag("symbol", SymbolName);
            WriteAttribute("set", "ERCOTONELINES");
            WriteAttribute("cam", Cam);
            WriteAttribute("set", "ERCOTONELINES");
            WriteAttribute("origin", Location.X + Offset.X, Location.Y + Offset.Y);
            WriteEndTag();
        }

        /// <summary>
        /// Write out an old-style picture with associated records
        /// </summary>
        /// <param name="SymbolName"></param>
        /// <param name="Location"></param>  
        /// <param name="Cam"></param>
        /// <param name="Offset"></param>
        /// <param name="ToolTip"></param>
        public void WriteSymbolWithCamAndToolTip(string SymbolName, Point Location, Point Offset, String Cam, String ToolTip)
        {
            WriteStartTag("symbol", SymbolName);
            WriteAttribute("set", "ERCOTONELINES");
            WriteAttribute("cam", Cam);
            WriteAttribute("set", "ERCOTONELINES");
            WriteAttribute("origin", Location.X + Offset.X, Location.Y + Offset.Y);
            WriteAttribute("tool_tip(localize \"" + ToolTip.Replace("\r\n", "\r\r\n") + "\")");
            WriteEndTag();
        }

        /// <summary>
        /// Write a single line, and if requested, an arrow on the receiving end
        /// </summary>
        /// <param name="Pt1">The start point</param>
        /// <param name="Pt2">The end point</param>
        /// <param name="ToArrow">Whether an arrow would be drawn</param>
        /// <param name="Gab">The name of the gab</param>
        public void WriteGraphicLine(Point Pt1, Point Pt2, bool ToArrow, string Gab)
        {
            WriteStartTag("polyline", "");
            WriteAttribute("gab", Gab);
            WriteAttribute("set", "ERCOTONELINES");
            WriteAttribute("origin", Pt1.X, Pt1.Y);


            WriteAttribute("point", Pt1.X, Pt1.Y);

            WriteAttribute("point", Pt2.X - Pt1.X, Pt2.Y - Pt1.Y);
            if (ToArrow)
            {
                double angle = Math.Atan2(Pt2.Y - Pt1.Y, Pt2.X - Pt1.X);
                float arrowsize = 8;
                double anglediff = Math.PI / 4.0;
                Point LeftSide = Point.Ceiling(new PointF((float)Math.Cos(angle - anglediff) * -arrowsize, (float)Math.Sin(angle - anglediff) * -arrowsize));
                Point RightSide = Point.Ceiling(new PointF((float)Math.Cos(angle + anglediff) * -arrowsize, (float)Math.Sin(angle + anglediff) * -arrowsize));
                WriteAttribute("point", LeftSide.X, LeftSide.Y);
                WriteAttribute("point", -LeftSide.X, -LeftSide.Y);
                WriteAttribute("point", RightSide.X, RightSide.Y);
            }
            //Determine the angle from pt1 to pt2



            WriteEndTag();
        }

        /// <summary>
        /// Write out a rectangle with specified gab
        /// </summary>
        /// <param name="Bounds"></param>
        /// <param name="Offset"></param>
        /// <param name="Gab"></param>
        /// <param name="XLocked"></param>
        /// <param name="YLocked"></param>
        public void WriteRectangle(Rectangle Bounds, Point Offset, string Gab, bool XLocked = false, bool YLocked = false)
        {
            WriteStartTag("rectangle", "");
            WriteAttribute("gab", Gab);
            WriteAttribute("set", "ERCOTONELINES");
            WriteAttribute("origin", Bounds.Left + Offset.X, Bounds.Top + Offset.Y);
            if (XLocked)
                WriteAttribute("xlocked");
            if (YLocked)
                WriteAttribute("ylocked");
            WriteAttribute("width", Bounds.Width);
            WriteAttribute("height", Bounds.Height);
            WriteEndTag();
        }

        /// <summary>
        /// Write out a rectangle with specified gab
        /// </summary>
        /// <param name="Bounds"></param>
        /// <param name="Offset"></param>
        /// <param name="BackColor"></param>
        /// <param name="ForeColor"></param>
        public void WriteRectangle(Rectangle Bounds, Point Offset, string ForeColor, string BackColor, bool XLocked = false, bool YLocked = false)
        {
            WriteStartTag("rectangle", "");
            WriteStartTag("gab", "");
            if (!String.IsNullOrEmpty(ForeColor))
                WriteAttribute("foreground", "White");
            if (!String.IsNullOrEmpty(BackColor))
                WriteAttribute("background", BackColor);
            WriteEndTag();
            WriteAttribute("origin", Bounds.Left + Offset.X, Bounds.Top + Offset.Y);
           
            if (XLocked)
                WriteAttribute("xlocked");
            if (YLocked)
                WriteAttribute("ylocked");
            WriteAttribute("width", Bounds.Width);
            WriteAttribute("height", Bounds.Height);
            WriteEndTag();
        }

        /// <summary>
        /// Write out a rectangle with specified gab
        /// </summary>
        /// <param name="Bounds"></param>
        /// <param name="Offset"></param>
        /// <param name="ForeColor"></param>
        /// <param name="Comment"></param>
        public void WriteFilledRectangleWithComment(Rectangle Bounds, Point Offset, string ForeColor, string Comment)
        {
            WriteStartTag("rectangle", "");
            WriteStartTag("gab", "");
            WriteAttribute("foreground", ForeColor);
            WriteAttribute("fill");
            WriteEndTag();
            WriteAttribute("tool_tip(localize \"" + Comment.Replace("\r\n", "\r\r\n") + "\")");
            WriteAttribute("origin", Bounds.Left + Offset.X, Bounds.Top + Offset.Y);
            WriteAttribute("width", Bounds.Width);
            WriteAttribute("height", Bounds.Height);
            WriteEndTag();
        }

        /// <summary>
        /// Write out an ellipse with specified gab
        /// </summary>
        /// <param name="Bounds"></param>
        /// <param name="Offset"></param>
        /// <param name="BackColor"></param>
        /// <param name="ForeColor"></param>
        public void WriteEllipse(Rectangle Bounds, Point Offset, string ForeColor, string BackColor)
        {
            WriteStartTag("ellipse", "");
            WriteStartTag("gab", "");
            if (!String.IsNullOrEmpty(ForeColor))
                WriteAttribute("foreground", "White");
            if (!String.IsNullOrEmpty(BackColor))
                WriteAttribute("background", BackColor);
            WriteEndTag();
            WriteAttribute("origin", Bounds.Left + Offset.X, Bounds.Top + Offset.Y);
            WriteAttribute("width", Bounds.Width);
            WriteAttribute("height", Bounds.Height);
            WriteEndTag();
        }

        /// <summary>
        /// Write out a rectangle with specified gab
        /// </summary>
        /// <param name="Bounds"></param>
        /// <param name="Offset"></param>
        /// <param name="Gab"></param>
        /// <param name="Keyset"></param>
        public void WriteRectangleWithKeyset(Rectangle Bounds, Point Offset, string Gab, string Keyset)
        {
            WriteStartTag("rectangle", "");
            WriteAttribute("gab", Gab);
            WriteAttribute("set", "ERCOTONELINES");
            if (!String.IsNullOrEmpty(Keyset))
            {
                WriteAttribute("keyset", Keyset);
                WriteAttribute("set", "ERCOTONELINES");
            }
            WriteAttribute("origin", Bounds.Left + Offset.X, Bounds.Top + Offset.Y);
            WriteAttribute("width", Bounds.Width);
            WriteAttribute("height", Bounds.Height);
            WriteEndTag();
        }

        /// <summary>
        /// Write out a rectangle with specified gab
        /// </summary>
        /// <param name="Bounds"></param>
        /// <param name="Offset"></param>
        /// <param name="Gab"></param>
        /// <param name="Keyset"></param>
        /// <param name="ToolTip"></param>
        public void WriteRectangleWithKeysetAndToolTip(Rectangle Bounds, Point Offset, string Gab, string Keyset, String ToolTip)
        {
            WriteStartTag("rectangle", "");
            WriteAttribute("gab", Gab);
            WriteAttribute("set", "ERCOTONELINES");
            if (!String.IsNullOrEmpty(Keyset))
            {
                WriteAttribute("keyset", Keyset);
                WriteAttribute("set", "ERCOTONELINES");
            }
            WriteAttribute("tool_tip(localize \"" + ToolTip.Replace("\r\n", "\r\r\n") + "\")");
            WriteAttribute("origin", Bounds.Left + Offset.X, Bounds.Top + Offset.Y);
            WriteAttribute("width", Bounds.Width);
            WriteAttribute("height", Bounds.Height);
            WriteEndTag();
        }

        /// <summary>
        /// Write out a rectangle with specified gab
        /// </summary>
        /// <param name="Bounds"></param>
        /// <param name="Offset"></param>
        /// <param name="Gab"></param>        
        /// <param name="Cam"></param>
        public void WriteRectangleWithCam(Rectangle Bounds, Point Offset, string Gab, String Cam)
        {
            WriteStartTag("rectangle", "");
            WriteAttribute("gab", Gab);
            WriteAttribute("set", "ERCOTONELINES");
            WriteAttribute("cam", Cam);
            WriteAttribute("set", "ERCOTONELINES");
            WriteAttribute("origin", Bounds.Left + Offset.X, Bounds.Top + Offset.Y);
            WriteAttribute("width", Bounds.Width);
            WriteAttribute("height", Bounds.Height);
            WriteEndTag();
        }


        /// <summary>
        /// Write out a rectangle with specified gab
        /// </summary>
        /// <param name="Bounds"></param>
        /// <param name="Offset"></param>
        /// <param name="Gab"></param>        
        /// <param name="Cam"></param>
        /// <param name="ToolTip"></param>
        public void WriteRectangleWithCamAndToolTip(Rectangle Bounds, Point Offset, string Gab, String Cam, String ToolTip)
        {
            WriteStartTag("rectangle", "");
            WriteAttribute("gab", Gab);
            WriteAttribute("set", "ERCOTONELINES");
            WriteAttribute("cam", Cam);
            WriteAttribute("set", "ERCOTONELINES");
            WriteAttribute("tool_tip(localize \"" + ToolTip.Replace("\r\n", "\r\r\n") + "\")");
            WriteAttribute("origin", Bounds.Left + Offset.X, Bounds.Top + Offset.Y);
            WriteAttribute("width", Bounds.Width);
            WriteAttribute("height", Bounds.Height);
            WriteEndTag();
        }

        /// <summary>
        /// Write out a rectangle with specified gab
        /// </summary>
        /// <param name="Bounds"></param>
        /// <param name="Offset"></param>
        /// <param name="Gab"></param>        
        /// <param name="Cam"></param>
        /// <param name="Keyset"></param>
        /// <param name="ToolTip"></param>
        public void WriteRectangleWithCamAndKeysetAndToolTip(Rectangle Bounds, Point Offset, string Gab, String Cam, string Keyset, String ToolTip)
        {
            WriteStartTag("rectangle", "");
            WriteAttribute("gab", Gab);
            WriteAttribute("set", "ERCOTONELINES");
            WriteAttribute("cam", Cam);
            WriteAttribute("set", "ERCOTONELINES");
            if (!String.IsNullOrEmpty(Keyset))
            {
                WriteAttribute("keyset", Keyset);
                WriteAttribute("set", "ERCOTONELINES");
            }
            WriteAttribute("tool_tip(localize \"" + ToolTip.Replace("\r\n", "\r\r\n") + "\")");
            WriteAttribute("origin", Bounds.Left + Offset.X, Bounds.Top + Offset.Y);
            WriteAttribute("width", Bounds.Width);
            WriteAttribute("height", Bounds.Height);
            WriteEndTag();
        }

        /// <summary>
        /// Write out a rectangle with specified gab
        /// </summary>
        /// <param name="Bounds"></param>
        /// <param name="Offset"></param>
        /// <param name="Gab"></param>        
        /// <param name="Cam"></param>
        /// <param name="Keyset"></param>
        public void WriteRectangleWithCamAndKeyset(Rectangle Bounds, Point Offset, string Gab, String Cam, string Keyset)
        {
            WriteStartTag("rectangle", "");
            WriteAttribute("gab", Gab);
            WriteAttribute("set", "ERCOTONELINES");
            WriteAttribute("cam", Cam);
            WriteAttribute("set", "ERCOTONELINES");
            if (!String.IsNullOrEmpty(Keyset))
            {
                WriteAttribute("keyset", Keyset);
                WriteAttribute("set", "ERCOTONELINES");
            }
            WriteAttribute("origin", Bounds.Left + Offset.X, Bounds.Top + Offset.Y);
            WriteAttribute("width", Bounds.Width);
            WriteAttribute("height", Bounds.Height);
            WriteEndTag();
        }

        /// <summary>
        /// Write a blank line
        /// </summary>
        public void WriteLine()
        {
            WriteLine(new String('\t', Indentation));
        }




        /// <summary>
        /// Write out text with a carriage return
        /// </summary>
        /// <param name="Text"></param>
        public void WriteLine(String Text)
        {
            if (Target != null)
                Target.WriteLine(Text);
        }

        /// <summary>
        /// Write out text with a carriage return
        /// </summary>
        /// <param name="Text"></param>
        public void Write(String Text)
        {
            if (Target != null)
                Target.Write(Text);
        }

        /// <summary>
        /// Close our string writer parentheses
        /// </summary>
        public void Close()
        {
            while (Indentation > 1)
                WriteEndTag();
            if (Target != null)
                Target.Close();
        }
        #endregion


        /// <summary>
        /// Handle disposal of the target
        /// </summary>
        public void Dispose()
        {
            if (Target != null)
                Target.Dispose();
        }
    }
}
